<?php
namespace Tbf\Bundle\DatabaseBundle\ThinkPhpModel;

/**
 * 模拟thinkphp的Model的数据库操作
 * mysql语句封装
 *   select(where) 查询
 *   insert(data) 插入 返回insertid
 *   update(data) 更新
 *   delete(where) 删除
 * 数据验证封装
 *   save(data)
 *   add(data) 同insert
 * 便捷方法封装
 *   findOne(where) 查询一条
 *   getField(field) 查询某项
 *   max(field) 最大值
 *   min(field) 最小值
 *   sum(field) 总和
 *   count(field) 总数
 *   rand(where) 随机一条
 *   exist(where) 是否存在
 * 低层次封装
 *   query(sql,data) pdo的parpare接口,返回二维数组,同tpdo
 *   getOne(sql,data) 返回一个字符串
 *   getRow(sql,data) 返回一行
 *
 * 连贯参数传入
 * table 表名
 * data  数据
 * field 字段
 * where
 * group
 * order
 * limit
 * assoc 关联字段
 * input
 *
 * debug 调试(显示执行的sql)
 *
 *
 * 与thinkphp的Model的不同:
 * 1.不验证数据
 * 2.无事件回调
 * 3.只支持mysql
 * 4.表名也是一个参数...
 * 5.其实还有很多..
 *
 * 本类测试覆盖比较全面
 *
   TODO: 更简单友好的调试方法
 * FIXME: 同时用where 和 input 传入数据的时候,会出现顺序错误
        $data = $this->getDb()
            ->table('cart_free_try_apply as a,cart_item as i')
            ->where(array(
                'a.status'=>$status,
                'a.apply_time >= ?',
                'a.itemid=i.itemid',
            ))
            ->input(TimeUtil::today())
            ->select();
       修改为1.where和input同时传入
  update和input同时传入
 * */
class ThinkPhpModel
{
    protected $curd = null;
    protected $db = null;
    protected $default_table_name = null;

    /**
     * @param Tpdo $tpdo
     * @param $curd
     */
    public function __construct($tpdo,$curd)
    {
        $this->db = $tpdo;
        $this->curd = $curd;
    }
    public function query($sql,$data=null,$debug=false)
    {
        return $this->db->query($sql,$data,$debug);
    }
    public function getOne($sql,$data=null,$debug=false)
    {
        return $this->db->getOne($sql,$data,$debug);
    }
    public function getRow($sql,$data=null,$debug=false)
    {
        return $this->db->getRow($sql,$data,$debug);
    }
    /**
     * mysql的select
     * 可传入where
     * 返回值[{'id':1,'name':'hehe'},{'id':2,'name':'hehe'}]
     */
    public function select($where=null)
    {
        if ($where!==null) {
            $this->setWhere($where);
        }
        $option = $this->getOption();
        $this->clearOption();
        $data = $this->curd->select($option);

        return $data;
    }
    /**
     * mysql的insert
     * 可传入data（需要插入的数据，关联数组）
     * 不检验数据
     * 返回插入id
     */
    public function insert($data=null)
    {
        if ($data!==null) {
            $this->setData($data);
        }
        $options = $this->getOption();
        $this->clearOption();
        $data = $this->curd->insert($options);

        return $data;
    }
    /**
     * mysql的update
     * 可传入data（需要更新的数据，关联数组）
     * 不检验数据
     * 返回true
     */
    public function update($data=null)
    {
        if ($data!==null) {
            $this->setData($data);
        }
        $option = $this->getOption();
        $this->clearOption();
        $data = $this->curd->update($option);

        return $data;
    }
    /**
     * mysql的delete
     * 可传入where
     * 返回true
     */
    public function delete($where=null)
    {
        if ($where!==null) {
            $this->setWhere($where);
        }
        $option = $this->getOption();
        $this->clearOption();
        $data = $this->curd->delete($option);

        return $data;
    }
    /**
     * 从数据里面找到第一个匹配项
     * 返回格式{'id':1,'name':'heh'}或[]
     */
    public function findOne($where=null)
    {
        if ($where!==null) {
            $this->setWhere($where);
        }
        $this->setLimit('1');
        $option = $this->getOption();
        $this->clearOption();
        $data = $this->curd->select($option);
        if (empty($data)) {
            return $data;
        }
        $data = $data[0];

        return $data;
    }
    /**
     * 保存这条数据
      @param array $data
      输入格式：
            {'id':1,'name':'hehe'}
     */
    public function save($data=null)
    {
        if ($data!==null) {
            $this->setData($data);
        }
        $data = $this->getData();
        if (!empty($data['id'])) {
            $where = $this->getWhere();
            $where['id'] = $data['id'];
            $this->setWhere($where);

            return $this->update($data);
        } else {
            return $this->insert($data);
        }
    }
    /**
     * 同insert
      @param array $data
      输入格式
     */
    public function add($data=null)
    {
        return $this->insert($data);
    }
    /**
     * 获取单一字段
     * 返回格式15
     */
    public function getField($field=null)
    {
        if ($field!==null) {
            $this->setField($field);
        }
        $data = $this->findOne();
        $data = array_pop($data);

        return $data;
    }
    /**
     * 获取对应字段的数据最大值
     * 返回格式15
     */
    public function max($field)
    {
        $field = 'MAX('.$field.') AS tbf_stat';

        return $this->getField($field);
    }
    /**
     * 获取对应字段的数据最小值
     * 返回格式int
     */
    public function min($field)
    {
        $field = 'MIN('.$field.') AS tbf_stat';

        return $this->getField($field);
    }
    /**
     * 获取对应字段的数据总和
     * 返回格式int
     */
    public function sum($field)
    {
        $field = 'SUM('.$field.') AS tbf_stat';

        return $this->getField($field);
    }
    /**
     * 获取满足要求的记录总数
     * 返回格式int
     */
    public function count($field=null)
    {
        if ($field===null) {
            $field = '*';
        }
        $field = 'COUNT('.$field.') AS tbf_stat';

        return $this->getField($field);
    }
    /**
     * 匹配集合里面随机取一个出来
     * 返回格式{'id':1,'name':'heh'}或[]
     */
    public function rand($where=null)
    {
        if ($where!==null) {
            $this->setWhere($where);
        }
        $option = $this->getOption();
        $totalNum = $this->setOption($option)->limit('1')->count();
        $theOne = rand(0,$totalNum-1);
        $data = $this->setOption($option)->limit($theOne.',1')->select();
        if (empty($data)) {
            return $data;
        }

        return $data[0];
    }
    /**
     * 判断传入的条件是否存在
      @param array $where
      @return bool
     */
    public function exist($where=null)
    {
        if ($where!==null) {
            $this->setWhere($where);
        }
        $ret = $this->getField('1');
        if (empty($ret)) {
            return false;
        } else {
            return true;
        }
    }
    public function getOption()
    {
        return $this->option;
    }
    public function setOption($option)
    {
        $this->option = $option;

        return $this;
    }
    public function clearOption()
    {
        $this->option = array();
        $this->setTable($this->default_table_name);

        return $this;
    }
    public function setDefaultTable($table_name)
    {
        $this->default_table_name = $table_name;
        $this->setTable($table_name);
    }
    public function setTable($table_name)
    {
        $this->option['table'] = $table_name;

        return $this;
    }
    public function table($table_name)
    {
        return $this->setTable($table_name);
    }
    public function setData($data)
    {
        $this->option['data'] = $data;

        return $this;
    }
    public function data($data)
    {
        return $this->setData($data);
    }
    public function getData()
    {
        return $this->option['data'];
    }
    public function setField($field)
    {
        $this->option['field'] = $field;

        return $this;
    }
    public function field($field)
    {
        return $this->setField($field);
    }
    public function setWhere($where)
    {
        $this->option['where'] = $where;

        return $this;
    }
    public function where($where)
    {
        return $this->setWhere($where);
    }
    public function getWhere()
    {
        if (empty($this->option['where'])) {
            return null;
        }

        return $this->option['where'];
    }
    public function group($group)
    {
        $this->option['group'] = $group;

        return $this;
    }
    public function order($order)
    {
        $this->option['order'] = $order;

        return $this;
    }
    public function setLimit($limit)
    {
        $this->option['limit'] = $limit;

        return $this;
    }
    public function limit($limit)
    {
        return $this->setLimit($limit);
    }
    public function input($input)
    {
        if (is_scalar($input)) {
            $this->option['input'][] = $input;

            return $this;
        }
        $this->option['input'] = $input;

        return $this;
    }
    public function assoc($assoc)
    {
        $this->option['assoc'] = $assoc;

        return $this;
    }
    public function debug($debug_func=true)
    {
        $this->option['debug'] = $debug_func;

        return $this;
    }
}
